package com.zjbd.douyangcommoncore.utils;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.File;
import java.util.Collections;

/**
 * MyBatis-Plus 代码生成工具类
 * 特性：每次生成时覆盖Entity，其他文件（Mapper、Service等）不覆盖，不生成Controller
 */
@Component
public class MyBatisPlusCodeGenerator {

    /**
     * 根据实体类信息生成代码（生成Entity并覆盖，根据配置生成Mapper/Service且不覆盖，不生成Controller）
     * @param dataSource 数据库连接池（从Spring容器中获取）
     * @param entityClass 实体类Class对象（用于计算包路径）
     * @param tableName 数据库表名
     * @param generateDao 是否生成DAO（Mapper）
     * @param generateService 是否生成Service
     */
    public static void generate(DataSource dataSource, Class<?> entityClass,
                                String tableName, boolean generateDao, boolean generateService) {
        // 1. 获取实体类所在包路径（如：com.zjbd.douyangcommoncore.entity）
        String entityPackage = entityClass.getPackage().getName();
        // 实体类所在模块的根路径（用于计算输出目录）
        String basePackage = entityPackage.substring(0, entityPackage.lastIndexOf("."));

        // 2. 计算代码输出路径（与实体类同级目录）
        String outputDirJava = getOutputDir(entityClass) + "java/";
        String outputDirSesources = getOutputDir(entityClass) + "resources/";

        // 3. 配置生成器
        FastAutoGenerator.create(new DataSourceConfig.Builder(dataSource))
                // 全局配置
                .globalConfig(builder -> {
                    builder.author("auto-generate")
                            .outputDir(outputDirJava)
                            .disableOpenDir() // 生成后不打开目录
                            .commentDate("yyyy-MM-dd"); // 统一注释日期格式
                })
                // 包配置
                .packageConfig(builder -> {
                    builder.parent(basePackage)
                            .entity("entity")       // Entity包名（与传入的实体类包一致）
                            .mapper("mapper")       // Mapper接口包名
                            .service("service")     // Service接口包名
                            .serviceImpl("service.impl") // Service实现类包名
                            .xml("mapper.xml");     // Mapper XML包名
                    // Mapper XML输出路径（确保目录存在）
                    File xmlDir = new File(outputDirSesources + "mapper/xml");
                    if (!xmlDir.exists()) {
                        xmlDir.mkdirs();
                    }
                    builder.pathInfo(Collections.singletonMap(OutputFile.xml, xmlDir.getAbsolutePath()));
                })
                // 策略配置（核心：Entity覆盖，其他不覆盖，禁用Controller）
                .strategyConfig(builder -> {
                    builder.addInclude(tableName); // 指定生成的表

                    // 1. 配置Entity：生成并强制覆盖
                    builder.entityBuilder()
                            .enableFileOverride() // 关键：每次生成覆盖已有Entity
                            .formatFileName("%s") // 实体类命名格式（默认与表名映射，如User表→User）
                            .enableLombok(); // 可选：如果使用Lombok，启用注解生成

                    // 2. 禁用Controller生成
                    builder.controllerBuilder().disable();

                    // 3. 配置Mapper：生成但不覆盖（默认不覆盖）
                    if (generateDao) {
                        builder.mapperBuilder()
                                .enableBaseResultMap()   // 生成基本的resultMap
                                .enableBaseColumnList()  // 生成基本的columnList
                                .formatMapperFileName("%sMapper") // Mapper接口命名格式
                                .formatXmlFileName("%sMapper");   // Mapper XML命名格式
                        // 不设置enableFileOverride()，默认不覆盖已有文件
                    } else {
                        builder.mapperBuilder().disable();
                    }

                    // 4. 配置Service：生成但不覆盖（默认不覆盖）
                    if (generateService) {
                        builder.serviceBuilder()
                                .formatServiceFileName("%sService")       // Service接口命名格式
                                .formatServiceImplFileName("%sServiceImpl"); // Service实现类命名格式
                        // 不设置enableFileOverride()，默认不覆盖已有文件
                    } else {
                        builder.serviceBuilder().disable();
                    }
                })
                // 模板引擎配置
                .templateEngine(new VelocityTemplateEngine())
                // 执行生成
                .execute();
    }

    /**
     * 计算实体类对应的代码输出目录（转换包路径为文件系统路径，兼容Windows/Linux）
     */
    private static String getOutputDir(Class<?> entityClass) {
        // 模块路径（使用File.separator兼容不同系统）
        String modelPath = File.separator + "DouYang-Common" + File.separator + "DouYang-Common-Core";
        // 获取项目根路径
        String projectPath = System.getProperty("user.dir");
        // 拼接最终输出路径（项目路径 + 模块路径 + java源码目录）
        String outputDir = projectPath + modelPath + "/src/main/";
        // 确保输出目录存在
        File dir = new File(outputDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        return outputDir;
    }

}